package com.simon.app.october.modules.job.utils;

import com.google.gson.Gson;
import com.simon.app.october.common.exception.OctoberException;
import com.simon.app.october.common.utils.Constant;
import com.simon.app.october.modules.job.entity.ScheduleJobEntity;
import org.quartz.*;

public class ScheduleUtil {

    private final static String JOB_NAME = "TASK_";

    private static JobKey getJobKey(long jobId) {
        return JobKey.jobKey(JOB_NAME+jobId);
    }

    private static TriggerKey getTriggerKey(long jobId) {
        return TriggerKey.triggerKey(JOB_NAME + jobId);
    }

    /**
     * 创建定时任务
     * */
    public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity jobEntity) {
        try {
            // 构建job
            JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class)
                    .withIdentity(getJobKey(jobEntity.getJobId()))
                    .build();
            // 放入参数，运行时方法可以取
            jobDetail.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, new Gson().toJson(jobEntity));

            // 构建cron
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                    .cronSchedule(jobEntity.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();

            // 根据cron，构建一个trigger
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(getTriggerKey(jobEntity.getJobId()))
                    .withSchedule(scheduleBuilder)
                    .build()
                    ;

            scheduler.scheduleJob(jobDetail, trigger);

            // 暂停任务
            if (jobEntity.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()) {
                //TODO
                pauseJob(scheduler, jobEntity.getJobId());
            }
        }catch (SchedulerException e) {
            throw new OctoberException("创建定时任务失败", e);
        }
    }

    /**
     * 更新任务
     * 源码这的功能只是换了一下trigger，其他的没变，不晓得为什么，有点搞笑
     * */
    public static void update(Scheduler scheduler, ScheduleJobEntity jobEntity) {
        try {
            // 获取当前的trigger key
            TriggerKey triggerKey = getTriggerKey(jobEntity.getJobId());

            // 生成最新的trigger
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                    .cronSchedule(jobEntity.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            trigger.getTriggerBuilder().withSchedule(scheduleBuilder).build();
            trigger.getJobDataMap().put(ScheduleJobEntity.JOB_PARAM_KEY, new Gson().toJson(jobEntity));

            scheduler.rescheduleJob(triggerKey, trigger);

            if (jobEntity.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()) {
                pauseJob(scheduler, jobEntity.getJobId());
            }
        }catch (SchedulerException e) {
            throw new OctoberException("更新定时任务失败", e);
        }
    }

    /**
     * 立即执行，没有指定trigger,只是单纯的执行jobDetail
     * */
    public static void run(Scheduler scheduler, ScheduleJobEntity entity) {
        try {
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(ScheduleJobEntity.JOB_PARAM_KEY, new Gson().toJson(entity));
            scheduler.triggerJob(getJobKey(entity.getJobId()), dataMap);
        } catch (SchedulerException e) {
            throw new OctoberException("立即执行任务失败", e);
        }
    }

    public static void pauseJob(Scheduler scheduler, long jobId) {
        try {
            scheduler.pauseJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new OctoberException("暂停任务失败", e);
        }
    }

    public static void resume(Scheduler scheduler, long jobId) {
        try {
            scheduler.resumeJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new OctoberException("重新启动任务失败", e);
        }
    }

    public static void delete(Scheduler scheduler, long jobId) {
        try {
            scheduler.deleteJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new OctoberException("删除定时任务失败", e);
        }
    }
}
